-
Notifications
You must be signed in to change notification settings - Fork 619
webhook multiselect topic #7818
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
WalkthroughThe changes introduce multi-signature selection support throughout the webhook creation and filtering workflow. Components, form schemas, and utility functions were updated to handle Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant CreateWebhookModal
participant FilterDetailsStep
participant SignatureSelector
participant webhookPayloadUtils
User->>CreateWebhookModal: Open modal
CreateWebhookModal->>FilterDetailsStep: Render filter step
FilterDetailsStep->>SignatureSelector: Render with multiSelect=true
User->>SignatureSelector: Select one or more signatures
SignatureSelector-->>FilterDetailsStep: onChange (string or string[])
FilterDetailsStep-->>CreateWebhookModal: Update form state (sigHash: string[])
User->>CreateWebhookModal: Submit form
CreateWebhookModal->>webhookPayloadUtils: build payload with sigHash (array)
webhookPayloadUtils-->>CreateWebhookModal: Payload with multiple signatures
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes ✨ Finishing Touches
🧪 Generate unit tests
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
How to use the Graphite Merge QueueAdd either label to this PR to merge it via the merge queue:
You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has enabled the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. |
size-limit report 📦
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #7818 +/- ##
=======================================
Coverage 56.33% 56.33%
=======================================
Files 905 905
Lines 58821 58821
Branches 4146 4146
=======================================
Hits 33137 33137
Misses 25578 25578
Partials 106 106
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🔭 Outside diff range comments (3)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/FilterDetailsStep.tsx (1)
453-457: ResetsigHashto [] instead of "" to align with multi-select semanticsUsing
""can cause subtle truthy checks and type churn (string vs string[]). Default to an empty array.- form.setValue("sigHash", ""); + form.setValue("sigHash", [] as string[]); form.setValue("sigHashAbi", "");- form.setValue("sigHash", ""); + form.setValue("sigHash", [] as string[]); form.setValue("sigHashAbi", "");Also applies to: 494-498
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/topic-selector-modal.tsx (2)
90-96: DefaultsigHashto [] to reflect multi-selectKeep form defaults consistent with multi-select to avoid type/UX inconsistencies.
- sigHash: "", + sigHash: [] as string[],Apply in both
eventFilterFormandtransactionFilterFormdefaults.Also applies to: 110-116
578-592: Normalize Input value forsigHashwhen it may be an arrayIf
sigHashbecomes an array, passing it directly toInputcan cause React warnings. Join to a string, mirroring the transaction branch.- <Input + <Input disabled={ (topic.id === "contracts.event.confirmed" && eventAbi.isFetching) || (topic.id === "contracts.transaction.confirmed" && txAbi.isFetching) } onChange={field.onChange} placeholder="Provide above details first..." - value={field.value} + value={ + Array.isArray(field.value) + ? field.value.join(", ") + : field.value || "" + } />
🧹 Nitpick comments (11)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/ReviewStep.tsx (1)
197-198: Avoid multiplewatch("sigHash")subscriptions; watch once and reuseRepeated calls can subscribe multiple times and produce inconsistent snapshots during render. Read once and reuse for label + value.
Apply:
- <span className="text-muted-foreground text-sm"> - Signature Hash{Array.isArray(form.watch("sigHash")) && form.watch("sigHash")?.length > 1 ? "es" : ""}: - </span> + {(() => { + const sigHash = form.watch("sigHash"); + const isPlural = Array.isArray(sigHash) && sigHash.length > 1; + return ( + <span className="text-muted-foreground text-sm"> + Signature Hash{isPlural ? "es" : ""}: + </span> + ); + })()} </span> <span className="font-medium text-sm"> {(() => { - const sigHash = form.watch("sigHash"); + const sigHash = form.watch("sigHash"); if (!sigHash) return "None"; - if (Array.isArray(sigHash)) { if (sigHash.length === 0) return "None"; if (sigHash.length === 1) { return truncateMiddle(sigHash[0], 10, 6); } return `${sigHash.length} signature${sigHash.length > 1 ? 's' : ''} selected`; } else { return truncateMiddle(sigHash, 10, 6); } })()}Also applies to: 200-213
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/utils/webhookPayloadUtils.ts (3)
36-47: Event signatures: logic is correct for multi-selectArray normalization + keccak256 fallback is sound. Payload omits signatures when none selected, which is ideal.
- Consider trimming user input:
const s = sigHash.trim(); if (!s) continue;- Avoid constructing TextEncoder in loop:
- for (const sigHash of sigHashes) { + const encoder = new TextEncoder(); + for (const sigHash of sigHashes) { if (sigHash) { eventSignatures.push({ abi: data.sigHashAbi || data.abi, params: {}, - sig_hash: sigHash.startsWith("0x") - ? sigHash - : keccak256(new TextEncoder().encode(sigHash)), + sig_hash: sigHash.startsWith("0x") + ? sigHash + : keccak256(encoder.encode(sigHash)), }); } }
67-77: Transaction signatures: correct selector handling for multiple entriesNormalization +
toFunctionSelectoris correct. Same minor improvements suggested for the event path apply here too.
- Trim input and skip empties.
- Avoid repeated work:
- for (const sigHash of sigHashes) { + for (const raw of sigHashes) { + const sigHash = raw.trim(); if (sigHash) { txSignatures.push({ abi: data.sigHashAbi || data.abi, params: {}, sig_hash: sigHash.startsWith("0x") ? sigHash : toFunctionSelector(sigHash), }); } }
36-47: Add explicit types for signatures arrays to satisfy TS guidelinesLocal arrays are inferred as
any[]. Define a shared type and annotate both arrays.Outside these hunks, add:
type SignatureEntry = { sig_hash: string; abi?: string; params: Record<string, unknown>; };Then update declarations:
// in buildEventWebhookPayload -const eventSignatures = []; +const eventSignatures: SignatureEntry[] = []; // in buildTransactionWebhookPayload -const txSignatures = []; +const txSignatures: SignatureEntry[] = [];Also applies to: 67-77
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/FilterDetailsStep.tsx (3)
138-145: Pluralize help text to match multi-address placeholderHelper text says “Enter a contract address” but the placeholder and parser support multiple. Align the copy to reduce confusion.
- <p className="text-muted-foreground"> - Enter a contract address - </p> + <p className="text-muted-foreground"> + Enter contract addresses (comma-separated) + </p>
343-364: Avoid duplicated onChange logic across event/transaction selectorsBoth handlers normalize
val, computeknown, and clearabiif any custom sig. Consider extracting a small helper to DRY this.Example extract outside the component:
function handleSignatureChange( val: string | string[], known: string[], onChange: (v: string[] | string) => void, clearAbi: () => void, ) { onChange(val); const values = Array.isArray(val) ? val : [val]; if (values.some((v) => v && !known.includes(v))) { clearAbi(); } }Then reuse in both places.
45-60: Add explicit return type on component per guidelinesDeclare the return type to
JSX.Element.-export function FilterDetailsStep({ +export function FilterDetailsStep({ form, eventSignatures, functionSignatures, fetchedAbis = {}, abiErrors = {}, fetchedTxAbis = {}, txAbiErrors = {}, isFetchingEventAbi, isFetchingTxAbi, goToNextStep, goToPreviousStep, isLoading, supportedChainIds, client, -}: FilterDetailsStepProps) { +}: FilterDetailsStepProps): JSX.Element {apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/topic-selector-modal.tsx (2)
446-449: Indicate multiple contract addresses in placeholderThe parser supports comma/space-separated addresses. Reflect that in the placeholder.
- <Input - placeholder="0x..." - {...field} - /> + <Input + placeholder="0x1234...,0xabcd..." + {...field} + />
61-66: Add explicit return type on component per guidelinesDeclare the return type for the modal component to
JSX.Element.-export function TopicSelectorModal(props: TopicSelectorModalProps) { +export function TopicSelectorModal(props: TopicSelectorModalProps): JSX.Element {apps/dashboard/src/@/components/blocks/SignatureSelector.tsx (2)
23-34: Add explicit return type on component per guidelinesDeclare
JSX.Elementon the component.-export function SignatureSelector({ +export function SignatureSelector({ options, value, onChange, setAbi, placeholder = "Select or enter a signature", disabled, secondaryTextFormatter, className, multiSelect = false, -}: SignatureSelectorProps) { +}: SignatureSelectorProps): JSX.Element {
106-119: Prevent duplicate custom values when pressing EnterCurrently, typing the same custom signature twice can append duplicates (since the check is only against
options). Guard against values already selected.const handleInputKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => { if (event.key === "Enter" && searchValue.trim()) { if (!options.some((opt) => opt.value === searchValue.trim())) { if (multiSelect) { // Add to existing values for multi-select - const currentArray = Array.isArray(value) ? value : (value ? [value] : []); + const currentArray = Array.isArray(value) ? value : (value ? [value] : []); const filteredArray = currentArray.filter((val): val is string => val !== undefined && val !== null); - const newValues = [...filteredArray, searchValue.trim()]; + const trimmed = searchValue.trim(); + if (filteredArray.includes(trimmed)) { + setSearchValue(""); + inputRef.current?.blur(); + return; + } + const newValues = [...filteredArray, trimmed]; onChange(newValues); } else { // Replace value for single-select onChange(searchValue.trim()); } if (setAbi) setAbi(""); setSearchValue(""); // Optionally blur input inputRef.current?.blur(); } } };
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx(5 hunks)apps/dashboard/src/@/components/blocks/multi-select.tsx(2 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/CreateWebhookModal.tsx(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/FilterDetailsStep.tsx(7 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/ReviewStep.tsx(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/topic-selector-modal.tsx(14 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/utils/webhookPayloadUtils.ts(2 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/utils/webhookTypes.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}
📄 CodeRabbit Inference Engine (CLAUDE.md)
**/*.{ts,tsx}: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity
Re-use shared types from@/typesor localtypes.tsbarrels
Prefer type aliases over interface except for nominal shapes
Avoidanyandunknownunless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial,Pick, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose
Files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/utils/webhookTypes.tsapps/dashboard/src/@/components/blocks/multi-select.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/CreateWebhookModal.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/ReviewStep.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/FilterDetailsStep.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/utils/webhookPayloadUtils.tsapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/topic-selector-modal.tsxapps/dashboard/src/@/components/blocks/SignatureSelector.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit Inference Engine (CLAUDE.md)
Load heavy dependencies inside async paths to keep initial bundle lean (lazy loading)
Files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/utils/webhookTypes.tsapps/dashboard/src/@/components/blocks/multi-select.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/CreateWebhookModal.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/ReviewStep.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/FilterDetailsStep.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/utils/webhookPayloadUtils.tsapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/topic-selector-modal.tsxapps/dashboard/src/@/components/blocks/SignatureSelector.tsx
apps/{dashboard,playground-web}/**/*.{ts,tsx}
📄 CodeRabbit Inference Engine (CLAUDE.md)
apps/{dashboard,playground-web}/**/*.{ts,tsx}: Import UI primitives from@/components/ui/*(Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps
UseNavLinkfor internal navigation with automatic active states in dashboard and playground apps
Use Tailwind CSS only – no inline styles or CSS modules
Usecn()from@/lib/utilsfor conditional class logic
Use design system tokens (e.g.,bg-card,border-border,text-muted-foreground)
Server Components (Node edge): Start files withimport "server-only";
Client Components (browser): Begin files with'use client';
Always callgetAuthToken()to retrieve JWT from cookies on server side
UseAuthorization: Bearerheader – never embed tokens in URLs
Return typed results (e.g.,Project[],User[]) – avoidany
Wrap client-side data fetching calls in React Query (@tanstack/react-query)
Use descriptive, stablequeryKeysfor React Query cache hits
ConfigurestaleTime/cacheTimein React Query based on freshness (default ≥ 60s)
Keep tokens secret via internal API routes or server actions
Never importposthog-jsin server components
Files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/utils/webhookTypes.tsapps/dashboard/src/@/components/blocks/multi-select.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/CreateWebhookModal.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/ReviewStep.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/FilterDetailsStep.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/utils/webhookPayloadUtils.tsapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/topic-selector-modal.tsxapps/dashboard/src/@/components/blocks/SignatureSelector.tsx
🧠 Learnings (27)
📚 Learning: 2025-06-10T00:55:19.140Z
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/form.ts:12-14
Timestamp: 2025-06-10T00:55:19.140Z
Learning: The NFT collection form (`nftCollectionInfoFormSchema`) in `apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/form.ts` is intentionally designed to only allow File uploads for the `image` field, not hosted URLs. The schema correctly uses `z.instanceof(File).optional()` to restrict image inputs to uploaded files only.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/utils/webhookTypes.tsapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/CreateWebhookModal.tsx
📚 Learning: 2025-06-26T19:46:04.024Z
Learnt from: gregfromstl
PR: thirdweb-dev/js#7450
File: packages/thirdweb/src/bridge/Webhook.ts:57-81
Timestamp: 2025-06-26T19:46:04.024Z
Learning: In the onramp webhook schema (`packages/thirdweb/src/bridge/Webhook.ts`), the `currencyAmount` field is intentionally typed as `z.number()` while other amount fields use `z.string()` because `currencyAmount` represents fiat currency amounts in decimals (like $10.50), whereas other amount fields represent token amounts in wei (very large integers that benefit from bigint representation). The different naming convention (`currencyAmount` vs `amount`) reflects this intentional distinction.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/utils/webhookTypes.tsapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/CreateWebhookModal.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/utils/webhookPayloadUtils.ts
📚 Learning: 2025-07-10T10:18:33.238Z
Learnt from: arcoraven
PR: thirdweb-dev/js#7505
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/analytics/components/WebhookAnalyticsCharts.tsx:186-204
Timestamp: 2025-07-10T10:18:33.238Z
Learning: The ThirdwebBarChart component in apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/analytics/components/WebhookAnalyticsCharts.tsx does not accept standard accessibility props like `aria-label` and `role` in its TypeScript interface, causing compilation errors when added.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/utils/webhookTypes.tsapps/dashboard/src/@/components/blocks/multi-select.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/CreateWebhookModal.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/ReviewStep.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/FilterDetailsStep.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/topic-selector-modal.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{ts,tsx} : Return typed results (e.g., `Project[]`, `User[]`) – avoid `any`
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/utils/webhookTypes.tsapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/CreateWebhookModal.tsx
📚 Learning: 2025-05-21T05:17:31.283Z
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/utils/webhookTypes.tsapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/CreateWebhookModal.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/ReviewStep.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/api/**/*.{ts,tsx} : Return typed results (`Project[]`, `User[]`, …) – avoid `any`.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/utils/webhookTypes.ts
📚 Learning: 2025-06-10T00:50:20.795Z
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/utils/webhookTypes.tsapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/CreateWebhookModal.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/ReviewStep.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/FilterDetailsStep.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/utils/webhookPayloadUtils.tsapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/topic-selector-modal.tsxapps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-06-10T15:59:29.585Z
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/_common/SocialUrls.tsx:24-25
Timestamp: 2025-06-10T15:59:29.585Z
Learning: In the SocialUrlsFieldset component in React Hook Form with TypeScript generics, when using useFieldArray with a generic form type T that extends WithSocialUrls, the type assertion `as unknown as UseFormReturn<WithSocialUrls>` is the preferred approach rather than trying to use `as keyof T`, because useFieldArray needs specific type information about the array field structure.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/utils/webhookTypes.tsapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/CreateWebhookModal.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/FilterDetailsStep.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/topic-selector-modal.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Anything that consumes hooks from `tanstack/react-query` or thirdweb SDKs.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/utils/webhookTypes.tsapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/CreateWebhookModal.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*.{tsx,jsx} : Prefer composable primitives over custom markup: `Button`, `Input`, `Select`, `Tabs`, `Card`, `Sidebar`, `Separator`, `Badge`.
Applied to files:
apps/dashboard/src/@/components/blocks/multi-select.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/CreateWebhookModal.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/ReviewStep.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/FilterDetailsStep.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/topic-selector-modal.tsxapps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{ts,tsx} : Import UI primitives from `@/components/ui/*` (Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps
Applied to files:
apps/dashboard/src/@/components/blocks/multi-select.tsxapps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*.{tsx,jsx} : Reuse core UI primitives; avoid re-implementing buttons, cards, modals.
Applied to files:
apps/dashboard/src/@/components/blocks/multi-select.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{tsx} : Expose `className` prop on root element of components for overrides
Applied to files:
apps/dashboard/src/@/components/blocks/multi-select.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Interactive UI that relies on hooks (`useState`, `useEffect`, React Query, wallet hooks).
Applied to files:
apps/dashboard/src/@/components/blocks/multi-select.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/CreateWebhookModal.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/FilterDetailsStep.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/topic-selector-modal.tsxapps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Components that listen to user events, animations or live updates.
Applied to files:
apps/dashboard/src/@/components/blocks/multi-select.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/FilterDetailsStep.tsx
📚 Learning: 2025-06-23T13:33:05.770Z
Learnt from: AmineAfia
PR: thirdweb-dev/js#7415
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/utils/abiUtils.ts:31-42
Timestamp: 2025-06-23T13:33:05.770Z
Learning: In the thirdweb webhooks ABI utilities, validation of ABI inputs is performed upstream using the `isAbiInput` function before calling `getCanonicalType`. The `getCanonicalType` function only receives pre-validated inputs, so additional runtime validation within the function would be redundant.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/CreateWebhookModal.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Surface breaking changes prominently in PR descriptions
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/ReviewStep.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/topic-selector-modal.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to **/*.{ts,tsx} : Comment only ambiguous logic; avoid restating TypeScript in prose
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/ReviewStep.tsx
📚 Learning: 2025-06-10T00:49:12.707Z
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/upload-nfts/single-upload/attributes.tsx:24-25
Timestamp: 2025-06-10T00:49:12.707Z
Learning: In React Hook Form with TypeScript generics, when using useFieldArray with a generic form type T that extends a specific interface, it's often necessary to use type assertions like `as unknown as UseFormReturn<WithAttributes>` rather than trying to use `as keyof T`. The type assertion approach works better because useFieldArray needs specific type information about the array field structure, and the generic constraint ensures the field exists safely.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/FilterDetailsStep.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/topic-selector-modal.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to packages/thirdweb/src/wallets/** : EIP-1193, EIP-5792, EIP-7702 standard support in wallet modules
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/utils/webhookPayloadUtils.ts
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Event name: human-readable `<subject> <verb>` phrase (e.g. "contract deployed").
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/topic-selector-modal.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to src/@/analytics/report.ts : Analytics event name: human-readable `<subject> <verb>` (e.g., "contract deployed"); function: `report<Subject><Verb>` (PascalCase)
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/topic-selector-modal.tsx
📚 Learning: 2025-06-13T13:50:08.622Z
Learnt from: MananTank
PR: thirdweb-dev/js#7332
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/nft/overview/nft-drop-claim.tsx:170-178
Timestamp: 2025-06-13T13:50:08.622Z
Learning: In event-tracking (`useTrack`) calls across the dashboard, the team intentionally keeps `contractType` generic as `"NFTCollection"` even for ERC-721 drops; contract differentiation is handled via the `ercType` field instead.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/topic-selector-modal.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*.{tsx,jsx} : Accept a typed `props` object and export a named function (`export function MyComponent()`).
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/topic-selector-modal.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to **/*.{ts,tsx} : Write idiomatic TypeScript with explicit function declarations and return types
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/topic-selector-modal.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to **/*.{ts,tsx} : Choose composition over inheritance; leverage utility types (`Partial`, `Pick`, etc.)
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to src/exports/react.native.ts : React Native specific exports are in `src/exports/react.native.ts`
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: Lint Packages
- GitHub Check: E2E Tests (pnpm, vite)
- GitHub Check: E2E Tests (pnpm, esbuild)
- GitHub Check: Unit Tests
- GitHub Check: Size
- GitHub Check: Analyze (javascript)
🔇 Additional comments (6)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/utils/webhookTypes.ts (1)
76-76: No remaining single-string assumptions forsigHash
Verified that all downstream handlers normalizesigHashto an array in:
webhookPayloadUtils.ts(lines 36, 67)ReviewStep.tsx(lines 197–202)CreateWebhookModal.tsx(line 68)FilterDetailsStep.tsx(line 79)topic-selector-modal.tsx(multiple occurrences)All usages guard against a lone string and wrap it in an array, so the schema change is fully supported.
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/CreateWebhookModal.tsx (1)
68-68: DefaultsigHashas [] aligns with multi-selectDefaulting to an empty array matches the updated schema and the new UI flows. No issues.
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/FilterDetailsStep.tsx (2)
79-85: Custom signature detection correctly handles single/multi valuesThe normalization to
sigHashesand.somechecks against known signatures looks correct and resilient.
319-338: Event signature selector multi-select usage looks goodPassing
multiSelect, normalizingvalueto an array, and clearingabion custom signatures are all correct. Good job keepingsigHashAbiseparate.apps/dashboard/src/@/components/blocks/SignatureSelector.tsx (2)
13-21: API surface for multi-select looks solidProp types (
valueandonChange) andmultiSelectflag correctly enable single/multi modes while keeping backward compatibility.Also applies to: 32-33
164-170: Clear, contextual guidance for custom entriesThe warning copy adapts to single/multi and is helpful. Nice touch.
...(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/topic-selector-modal.tsx
Show resolved
Hide resolved
...(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/topic-selector-modal.tsx
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (2)
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx (2)
47-64: Reduce branching by normalisingvalueonceThe current
currentValuesmemo has four nested branches and repeats the same null/undefined filtering.
Normalisingvalueto an array up-front makes the intent clearer and avoids edge-cases.-const currentValues = useMemo((): string[] => { - if (multiSelect) { - if (Array.isArray(value)) { - return value.filter((val): val is string => val !== undefined && val !== null); - } else { - return value ? [value] : []; - } - } else { - if (Array.isArray(value)) { - return value.length > 0 && value[0] ? [value[0]] : []; - } else { - return value ? [value] : []; - } - } -}, [value, multiSelect]); +const currentValues = useMemo(() => { + const arr = Array.isArray(value) ? value : [value]; + return arr.filter(Boolean) as string[]; +}, [value]);This also prevents accidental duplication when
multiSelectis false but an array is passed.
115-140: CallpreventDefault()on Enter to stop unintended form submitsPressing Enter inside the search input can bubble up and trigger a surrounding
<form>submit. Addevent.preventDefault()(and optionallyevent.stopPropagation()) before mutating state:-if (event.key === "Enter" && searchValue.trim()) { +if (event.key === "Enter" && searchValue.trim()) { + event.preventDefault();Minor, but it avoids accidental navigation and improves accessibility.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx(5 hunks)apps/dashboard/src/@/components/blocks/multi-select.tsx(2 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/FilterDetailsStep.tsx(7 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/ReviewStep.tsx(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/utils/webhookPayloadUtils.ts(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/utils/webhookPayloadUtils.ts
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/ReviewStep.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/FilterDetailsStep.tsx
- apps/dashboard/src/@/components/blocks/multi-select.tsx
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}
📄 CodeRabbit Inference Engine (CLAUDE.md)
**/*.{ts,tsx}: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity
Re-use shared types from@/typesor localtypes.tsbarrels
Prefer type aliases over interface except for nominal shapes
Avoidanyandunknownunless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial,Pick, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose
Files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit Inference Engine (CLAUDE.md)
Load heavy dependencies inside async paths to keep initial bundle lean (lazy loading)
Files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
apps/{dashboard,playground-web}/**/*.{ts,tsx}
📄 CodeRabbit Inference Engine (CLAUDE.md)
apps/{dashboard,playground-web}/**/*.{ts,tsx}: Import UI primitives from@/components/ui/*(Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps
UseNavLinkfor internal navigation with automatic active states in dashboard and playground apps
Use Tailwind CSS only – no inline styles or CSS modules
Usecn()from@/lib/utilsfor conditional class logic
Use design system tokens (e.g.,bg-card,border-border,text-muted-foreground)
Server Components (Node edge): Start files withimport "server-only";
Client Components (browser): Begin files with'use client';
Always callgetAuthToken()to retrieve JWT from cookies on server side
UseAuthorization: Bearerheader – never embed tokens in URLs
Return typed results (e.g.,Project[],User[]) – avoidany
Wrap client-side data fetching calls in React Query (@tanstack/react-query)
Use descriptive, stablequeryKeysfor React Query cache hits
ConfigurestaleTime/cacheTimein React Query based on freshness (default ≥ 60s)
Keep tokens secret via internal API routes or server actions
Never importposthog-jsin server components
Files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
🧠 Learnings (7)
📓 Common learnings
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Surface breaking changes prominently in PR descriptions
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*.{tsx,jsx} : Prefer composable primitives over custom markup: `Button`, `Input`, `Select`, `Tabs`, `Card`, `Sidebar`, `Separator`, `Badge`.
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Interactive UI that relies on hooks (`useState`, `useEffect`, React Query, wallet hooks).
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-06-10T00:50:20.795Z
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{ts,tsx} : Import UI primitives from `@/components/ui/*` (Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to **/*.{ts,tsx} : Choose composition over inheritance; leverage utility types (`Partial`, `Pick`, etc.)
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to src/exports/react.native.ts : React Native specific exports are in `src/exports/react.native.ts`
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
- GitHub Check: Size
- GitHub Check: Unit Tests
- GitHub Check: Build Packages
- GitHub Check: E2E Tests (pnpm, vite)
- GitHub Check: Lint Packages
- GitHub Check: E2E Tests (pnpm, esbuild)
- GitHub Check: E2E Tests (pnpm, webpack)
- GitHub Check: Analyze (javascript)
jnsdls
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
look at 🐰 and try to incorporate, otherwise LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🔭 Outside diff range comments (1)
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx (1)
1-4: Missing'use client'directiveThis component uses React hooks, so it must start with
'use client';to be treated as a client component in Next.js.
Add it as the very first line.+'use client'; import { useCallback, useMemo, useRef, useState } from "react";
♻️ Duplicate comments (2)
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx (2)
11-21: Use a discriminated union for props
Currentvalue/onChangeunions aren’t tied tomultiSelect, letting invalid combos through. The earlier review already provided a union example; please apply it for compile-time safety.
88-106: De-duplicate selections in multi-select mode
onChange(selected)forwards the array verbatim, so the same signature can be added multiple times (e.g., via manual input). Deduplicate before propagating:- onChange(selected); + onChange([...new Set(selected)]);
🧹 Nitpick comments (1)
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx (1)
94-101: Avoid redundantsetAbicalls
setAbifires every selection change even when the ABI hasn’t changed. Cache the previous ABI or compare before updating to prevent unnecessary re-renders.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx(5 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/ReviewStep.tsx(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/topic-selector-modal.tsx(14 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/ReviewStep.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/topic-selector-modal.tsx
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}
📄 CodeRabbit Inference Engine (CLAUDE.md)
**/*.{ts,tsx}: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity
Re-use shared types from@/typesor localtypes.tsbarrels
Prefer type aliases over interface except for nominal shapes
Avoidanyandunknownunless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial,Pick, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose
Files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit Inference Engine (CLAUDE.md)
Load heavy dependencies inside async paths to keep initial bundle lean (lazy loading)
Files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
apps/{dashboard,playground-web}/**/*.{ts,tsx}
📄 CodeRabbit Inference Engine (CLAUDE.md)
apps/{dashboard,playground-web}/**/*.{ts,tsx}: Import UI primitives from@/components/ui/*(Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps
UseNavLinkfor internal navigation with automatic active states in dashboard and playground apps
Use Tailwind CSS only – no inline styles or CSS modules
Usecn()from@/lib/utilsfor conditional class logic
Use design system tokens (e.g.,bg-card,border-border,text-muted-foreground)
Server Components (Node edge): Start files withimport "server-only";
Client Components (browser): Begin files with'use client';
Always callgetAuthToken()to retrieve JWT from cookies on server side
UseAuthorization: Bearerheader – never embed tokens in URLs
Return typed results (e.g.,Project[],User[]) – avoidany
Wrap client-side data fetching calls in React Query (@tanstack/react-query)
Use descriptive, stablequeryKeysfor React Query cache hits
ConfigurestaleTime/cacheTimein React Query based on freshness (default ≥ 60s)
Keep tokens secret via internal API routes or server actions
Never importposthog-jsin server components
Files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
🧠 Learnings (18)
📓 Common learnings
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Surface breaking changes prominently in PR descriptions
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*.{tsx,jsx} : Prefer composable primitives over custom markup: `Button`, `Input`, `Select`, `Tabs`, `Card`, `Sidebar`, `Separator`, `Badge`.
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Interactive UI that relies on hooks (`useState`, `useEffect`, React Query, wallet hooks).
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to **/*.{ts,tsx} : Choose composition over inheritance; leverage utility types (`Partial`, `Pick`, etc.)
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{ts,tsx} : Import UI primitives from `@/components/ui/*` (Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-06-10T00:50:20.795Z
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to src/exports/react.native.ts : React Native specific exports are in `src/exports/react.native.ts`
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to **/*.{ts,tsx} : Avoid `any` and `unknown` unless unavoidable; narrow generics when possible
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{ts,tsx} : Return typed results (e.g., `Project[]`, `User[]`) – avoid `any`
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to **/*.{ts,tsx} : Write idiomatic TypeScript with explicit function declarations and return types
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to **/*.{ts,tsx} : Prefer type aliases over interface except for nominal shapes
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to **/*.{ts,tsx} : Comment only ambiguous logic; avoid restating TypeScript in prose
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to **/*.{ts,tsx} : Limit each file to one stateless, single-responsibility function for clarity
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-06-10T15:59:29.585Z
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/_common/SocialUrls.tsx:24-25
Timestamp: 2025-06-10T15:59:29.585Z
Learning: In the SocialUrlsFieldset component in React Hook Form with TypeScript generics, when using useFieldArray with a generic form type T that extends WithSocialUrls, the type assertion `as unknown as UseFormReturn<WithSocialUrls>` is the preferred approach rather than trying to use `as keyof T`, because useFieldArray needs specific type information about the array field structure.
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*.{tsx,jsx} : Reuse core UI primitives; avoid re-implementing buttons, cards, modals.
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to src/@/analytics/report.ts : Review `src/@/analytics/report.ts` before adding analytics events to check for duplicates
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Components that listen to user events, animations or live updates.
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-06-24T21:38:03.155Z
Learnt from: MananTank
PR: thirdweb-dev/js#7434
File: apps/dashboard/src/app/(app)/team/~/~/contract/[chain]/[contractAddress]/components/project-selector.tsx:62-76
Timestamp: 2025-06-24T21:38:03.155Z
Learning: In the project-selector.tsx component for contract imports, the addToProject.mutate() call is intentionally not awaited (fire-and-forget pattern) to allow immediate navigation to the contract page while the import happens in the background. This is a deliberate design choice to prioritize user experience.
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Size
| const currentArray = Array.isArray(value) | ||
| ? value | ||
| : value | ||
| ? [value] | ||
| : []; | ||
| const filteredArray = currentArray.filter( | ||
| (val): val is string => val !== undefined && val !== null, | ||
| ); | ||
| const newValues = [...filteredArray, searchValue.trim()]; | ||
| onChange(newValues); | ||
| } else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also de-duplicate when adding custom values
The manual-input path appends searchValue without checking for duplicates, leading to repeated entries. Apply the same new Set(...) pattern here.
🤖 Prompt for AI Agents
In apps/dashboard/src/@/components/blocks/SignatureSelector.tsx around lines 123
to 133, the code appends searchValue to the array without removing duplicates,
causing repeated entries. To fix this, wrap the combined array of filteredArray
and searchValue.trim() with a new Set to eliminate duplicates before converting
it back to an array. Then pass this deduplicated array to onChange.
Merge activity
|
<!-- start pr-codex -->
## PR-Codex overview
This PR focuses on modifying the handling of `sigHash` to support both single and multiple signature inputs across various components, improving user experience and functionality.
### Detailed summary
- Changed `sigHash` from a string to an array in multiple components.
- Updated validation and handling of `sigHash` in forms and utilities.
- Enhanced UI to reflect multiple signature selections.
- Adjusted props and methods to support multi-select functionality in `SignatureSelector` and related components.
> ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}`
<!-- end pr-codex -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit
* **New Features**
* Added support for selecting multiple signature hashes in webhook filters and selectors.
* Enhanced signature selectors to allow both single-select and multi-select modes, with improved handling of custom signatures.
* **Improvements**
* Updated UI labels, placeholders, and descriptions to reflect multi-selection capabilities and pluralization.
* Review and summary steps now display multiple selected signatures with appropriate formatting.
* Webhook payloads and validation schemas now support arrays of signature hashes for improved flexibility.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
80a9fac to
f92201d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (2)
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx (2)
11-15: Type-safety gap still unresolvedThe props still rely on
string | string[]instead of a discriminated union keyed onmultiSelect, so misuse is not caught at compile-time. See earlier review for the suggested union definition.Also applies to: 20-20
90-101: Duplicate entries can still slip through
selectedand the array built after manual entry are forwarded as-is, so the same signature can be added multiple times. Deduplicate before callingonChange, e.g.:- onChange(selected); + onChange([...new Set(selected)]);and
- const newValues = [...filteredArray, searchValue.trim()]; + const newValues = [...new Set([...filteredArray, searchValue.trim()])];Also applies to: 121-133
🧹 Nitpick comments (1)
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx (1)
80-85: Possible duplicate option objects
allOptionsconcatenatesformattedOptionswithcustomOptionseven when a custom value already exists in thecustomOptionsarray from a previous render, producing duplicate entries in the dropdown. Guard with aSetonvaluebefore mapping, or dedupe after concatenation.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx(5 hunks)apps/dashboard/src/@/components/blocks/multi-select.tsx(2 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/CreateWebhookModal.tsx(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/FilterDetailsStep.tsx(7 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/ReviewStep.tsx(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/topic-selector-modal.tsx(14 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/utils/webhookPayloadUtils.ts(2 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/utils/webhookTypes.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (7)
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/utils/webhookTypes.ts
- apps/dashboard/src/@/components/blocks/multi-select.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/utils/webhookPayloadUtils.ts
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/topic-selector-modal.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/CreateWebhookModal.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/ReviewStep.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/FilterDetailsStep.tsx
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}
📄 CodeRabbit Inference Engine (CLAUDE.md)
**/*.{ts,tsx}: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity
Re-use shared types from@/typesor localtypes.tsbarrels
Prefer type aliases over interface except for nominal shapes
Avoidanyandunknownunless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial,Pick, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose
Files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit Inference Engine (CLAUDE.md)
Load heavy dependencies inside async paths to keep initial bundle lean (lazy loading)
Files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
apps/{dashboard,playground-web}/**/*.{ts,tsx}
📄 CodeRabbit Inference Engine (CLAUDE.md)
apps/{dashboard,playground-web}/**/*.{ts,tsx}: Import UI primitives from@/components/ui/*(Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps
UseNavLinkfor internal navigation with automatic active states in dashboard and playground apps
Use Tailwind CSS only – no inline styles or CSS modules
Usecn()from@/lib/utilsfor conditional class logic
Use design system tokens (e.g.,bg-card,border-border,text-muted-foreground)
Server Components (Node edge): Start files withimport "server-only";
Client Components (browser): Begin files with'use client';
Always callgetAuthToken()to retrieve JWT from cookies on server side
UseAuthorization: Bearerheader – never embed tokens in URLs
Return typed results (e.g.,Project[],User[]) – avoidany
Wrap client-side data fetching calls in React Query (@tanstack/react-query)
Use descriptive, stablequeryKeysfor React Query cache hits
ConfigurestaleTime/cacheTimein React Query based on freshness (default ≥ 60s)
Keep tokens secret via internal API routes or server actions
Never importposthog-jsin server components
Files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
🧠 Learnings (19)
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*.{tsx,jsx} : Prefer composable primitives over custom markup: `Button`, `Input`, `Select`, `Tabs`, `Card`, `Sidebar`, `Separator`, `Badge`.
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-06-10T00:50:20.795Z
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Interactive UI that relies on hooks (`useState`, `useEffect`, React Query, wallet hooks).
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{ts,tsx} : Import UI primitives from `@/components/ui/*` (Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to **/*.{ts,tsx} : Choose composition over inheritance; leverage utility types (`Partial`, `Pick`, etc.)
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to **/*.{ts,tsx} : Avoid `any` and `unknown` unless unavoidable; narrow generics when possible
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{ts,tsx} : Return typed results (e.g., `Project[]`, `User[]`) – avoid `any`
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to **/*.{ts,tsx} : Write idiomatic TypeScript with explicit function declarations and return types
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to **/*.{ts,tsx} : Prefer type aliases over interface except for nominal shapes
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to **/*.{ts,tsx} : Comment only ambiguous logic; avoid restating TypeScript in prose
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to **/*.{ts,tsx} : Limit each file to one stateless, single-responsibility function for clarity
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-06-10T15:59:29.585Z
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/_common/SocialUrls.tsx:24-25
Timestamp: 2025-06-10T15:59:29.585Z
Learning: In the SocialUrlsFieldset component in React Hook Form with TypeScript generics, when using useFieldArray with a generic form type T that extends WithSocialUrls, the type assertion `as unknown as UseFormReturn<WithSocialUrls>` is the preferred approach rather than trying to use `as keyof T`, because useFieldArray needs specific type information about the array field structure.
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*.{tsx,jsx} : Reuse core UI primitives; avoid re-implementing buttons, cards, modals.
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to src/@/analytics/report.ts : Review `src/@/analytics/report.ts` before adding analytics events to check for duplicates
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Components that listen to user events, animations or live updates.
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-06-24T21:38:03.155Z
Learnt from: MananTank
PR: thirdweb-dev/js#7434
File: apps/dashboard/src/app/(app)/team/~/~/contract/[chain]/[contractAddress]/components/project-selector.tsx:62-76
Timestamp: 2025-06-24T21:38:03.155Z
Learning: In the project-selector.tsx component for contract imports, the addToProject.mutate() call is intentionally not awaited (fire-and-forget pattern) to allow immediate navigation to the contract page while the import happens in the background. This is a deliberate design choice to prioritize user experience.
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Keep `queryKey` stable and descriptive for cache hits.
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{ts,tsx} : Use descriptive, stable `queryKeys` for React Query cache hits
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*.{tsx,jsx} : Keep components pure; fetch data outside (server component or hook) and pass it down via props.
Applied to files:
apps/dashboard/src/@/components/blocks/SignatureSelector.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
- GitHub Check: Size
- GitHub Check: E2E Tests (pnpm, esbuild)
- GitHub Check: Unit Tests
- GitHub Check: E2E Tests (pnpm, webpack)
- GitHub Check: E2E Tests (pnpm, vite)
- GitHub Check: Build Packages
- GitHub Check: Lint Packages
- GitHub Check: Analyze (javascript)
PR-Codex overview
This PR focuses on updating the handling of
sigHashin the webhook components to support both single and multiple signature inputs, enhancing user experience and data management.Detailed summary
sigHashfrom a string to an array in multiple components.SignatureSelectorto support multi-select functionality.Summary by CodeRabbit
New Features
Improvements